#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef struct {
    unsigned short header;
    unsigned char type;
    unsigned short year;
    unsigned char month;
    unsigned char date;
    unsigned char hour;
    unsigned char min;
    unsigned char sec;
    unsigned short ms;
    unsigned short tail;
}__attribute__((packed)) SysDtime;

static int udp_data_socket = 0;
void SCOKET_UDP_RADI(struct sockaddr_in *client_addr,
                     struct sockaddr_in *local_addr,
                     int local_addr_len)
{
    //网络相关配置
    local_addr->sin_family = AF_INET;
    local_addr->sin_port = htons(64000);
    local_addr->sin_addr.s_addr = htonl(INADDR_ANY);

    udp_data_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (udp_data_socket < 0)
    {
        printf("#ERR: socket failed ! udp_data_socket: %d \n", udp_data_socket);
        return;
    }
    int ret = bind(udp_data_socket, (struct sockaddr *)local_addr, local_addr_len);

    if (ret < 0)
    {
        printf("#ERR: err to bind socket, err code: %d \n", ret);
        return;
    }
}

#include <pthread.h>
#include <time.h>
static unsigned char sys_time[30] = { 0 };
static volatile int thread_flag = 0;
void * update_systime() {
    thread_flag = 1;
    system(sys_time);
    system("hwclock -w");  //刷新到硬件时钟上
    thread_flag = 0;
}
void check_update(SysDtime * sdtime) {
    time_t timep;
    time(&timep);
    struct tm *tm = localtime(&timep);

    // printf("%04d年%02d月%02d日 %02d时%02d分%02d秒 \n", sdtime->year,sdtime->month,sdtime->date,sdtime->hour,sdtime->min,sdtime->sec);

    if(tm->tm_year+ 1900 == sdtime->year) {
        if(tm->tm_mon + 1 == sdtime->month) {
            if(tm->tm_mday == sdtime->date) {
                if(tm->tm_hour == sdtime->hour){
                    if(tm->tm_min == sdtime->min) {
                        if(tm->tm_sec == sdtime->sec) {
                            return;
                        }
                    }
                }
            }
        }
    }
    if(thread_flag == 1) return;
    sprintf(&sys_time, "date -s \"%04d-%02d-%02d %02d:%02d:%02d\"", sdtime->year,sdtime->month,sdtime->date,sdtime->hour,sdtime->min,sdtime->sec);
    pthread_t update_systime_id;
    pthread_create(&update_systime_id, NULL, update_systime, NULL);
}

void create_sysdtime() {
    struct sockaddr_in client_addr = {0};
    struct sockaddr_in local_addr = {0};
    struct ip_mreq mreq; // 多播地址结构体
    SCOKET_UDP_RADI(&client_addr, &local_addr, sizeof(local_addr));
    if(udp_data_socket < 0) {
        printf("error create udp radi \n");
    }
    unsigned char dbuf[100] = { 0 }; 
    
	int addrLen = sizeof(struct sockaddr_in);
    SysDtime *sdtime;
    while(1) {
        int dlen = recvfrom(udp_data_socket, &dbuf, 100, 0, (struct sockaddr *)&client_addr, &addrLen);
        if(dlen < 0) {
            continue;
        }
        if(dbuf[2] == 0x0f) {
            sdtime = (struct SysDtime *) dbuf;
            if(sdtime->header != 0xC8C9) {
                continue;
            }
            check_update(sdtime);
        }
    }
}
int main(int argc, char const *argv[])
{
    create_sysdtime();
    return 0;
}
